package com.monika.main.system.completable;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author:whh
 * @date: 2024-12-12 21:38
 * <p></p>
 */
public class CompletableFutureUtil {





    private static volatile CompletableFutureUtil instance;


    private static ExecutorService executor;

    private static final int nThreads = 5;


    private  CompletableFutureUtil() {
        executor = new ThreadPoolExecutor(nThreads,nThreads,
                0L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                new BasicThreadFactory.Builder().daemon(true).namingPattern("CompletableFutureUtil-Thread-%s").build());
    }


    public static CompletableFutureUtil getInstance(){

        if (instance == null){

            synchronized (CompletableFutureUtil.class){

                if(instance == null){
                    instance = new CompletableFutureUtil();
                }
            }
        }
        return instance;
    }






    public <T> List<T> all(FutureFunction<T> ... arr){
        List<T> result = new ArrayList<>();
        List<CompletableFuture<T>> ll = new ArrayList<>();
        for (FutureFunction<T> f : arr) {
            CompletableFuture<T> ctf = CompletableFuture.supplyAsync(f, executor).exceptionally(f);
            ll.add(ctf);
        }
        CompletableFuture<Void> all = CompletableFuture.allOf(ll.stream().toArray(len -> new CompletableFuture[len]));
        try {
            all.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }

        for (CompletableFuture<T> future : ll) {
            try {
               result.add(future.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

        return result;
    }


}
